<!DOCTYPE html>
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  <meta name="description" content="along&#39;s blog">
  <meta name="keyword" content="hexo-theme, vuejs">
  
    <link rel="shortcut icon" href="/css/images/logo.png">
  
  <title>
    
      自动化构建 | ALONG
    
  </title>
  <link href="/cdn.along/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <link href="/cdn.along/nprogress/0.2.0/nprogress.min.css" rel="stylesheet">
  <link href="/cdn.along/highlight.js/9.12.0/styles/tomorrow.min.css" rel="stylesheet">
  
<link rel="stylesheet" href="/css/style.css">

  
  <script src="/cdn.along/jquery/3.2.1/jquery.min.js"></script>
  <script src="/cdn.along/geopattern/1.2.3/js/geopattern.min.js"></script>
  <script src="/cdn.along/nprogress/0.2.0/nprogress.min.js"></script>
  
    
<script src="/js/qrious.js"></script>

  
  
  
  
    <!-- MathJax support START -->
    <script type="text/x-mathjax-config">
      MathJax.Hub.Config({
        tex2jax: {
          inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
          processEscapes: true,
          skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
        }
      });
    </script>

    <script type="text/x-mathjax-config">
      MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for (i=0; i < all.length; i += 1) {
          all[i].SourceElement().parentNode.className += ' has-jax';
        }
      });
    </script>
    <script type="text/javascript" src="/cdn.along/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
    <!-- MathJax support END -->
  


  
  
    
<script src="/js/local-search.js"></script>


<meta name="generator" content="Hexo 5.4.0"></head>
<div class="wechat-share">
  <img src="/css/images/logo.png" />
</div>
  <body>
    <header class="header fixed-header">
  <div class="header-container">
    <a class="home-link" href="/">
      <div class="logo"></div>
      <span>ALONG</span>
    </a>
    <ul class="right-list">
      
        <li class="list-item">
          
            <a href="/" class="item-link">Home</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/tags/" class="item-link">Tags</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/archives/" class="item-link">Archives</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/about/" class="item-link">About</a>
          
        </li>
      
      
        <li class="menu-item menu-item-search right-list">
    <a role="button" class="popup-trigger">
        <i class="fa fa-search fa-fw"></i>
    </a>
</li>
      
    </ul>
    <div class="menu">
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </div>
    <div class="menu-mask">
      <ul class="menu-list">
        
          <li class="menu-item">
            
              <a href="/" class="menu-link">Home</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/tags/" class="menu-link">Tags</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/archives/" class="menu-link">Archives</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/about/" class="menu-link">About</a>
            
          </li>
        
      </ul>
    </div>
    
      <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
            <span class="search-icon">
                <i class="fa fa-search"></i>
            </span>
            <div class="search-input-container">
                <input autocomplete="off" autocapitalize="off"
                    placeholder="Please enter your keyword(s) to search." spellcheck="false"
                    type="search" class="search-input">
            </div>
            <span class="popup-btn-close">
                <i class="fa fa-times-circle"></i>
            </span>
        </div>
        <div id="search-result">
            <div id="no-result">
                <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
            </div>
        </div>
    </div>
</div>
    
  </div>
</header>

    <div id="article-banner">
  <h2>自动化构建</h2>
  <p class="post-date">2020-08-27</p>
  <div class="arrow-down">
    <a href="javascript:;"></a>
  </div>
</div>
<main class="app-body flex-box">
  <!-- Article START -->
  <article class="post-article">
    <section class="markdown-content"><h2 id="前端自动化"><a href="#前端自动化" class="headerlink" title="前端自动化"></a>前端自动化</h2><p>前端自动化构建工具</p>
<ul>
<li>grunt 基于临时文件，构建速度较慢</li>
<li>gulp 基于内存，同时处理多个任务</li>
<li>FIS 百度，大而全，适合初学者</li>
</ul>
<h3 id="grunt"><a href="#grunt" class="headerlink" title="grunt"></a>grunt</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add grunt</span><br></pre></td></tr></table></figure>

<p>根目录创建<code>gruntfile.js</code>文件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">module.exports &#x3D; grunt &#x3D;&gt; &#123;</span><br><span class="line">    grunt.registerTask(&#39;hello&#39;, () &#x3D;&gt; &#123;</span><br><span class="line">        console.log(&#39;hello world&#39;);</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>命令行执行 <code>yarn grunt hello</code><br>可以看到命令行打印hello world</p>
<p>可以通过注册函数 第二个参数为字符串，来为任务添加描述，这个描述会通过<code>yarn grun --help</code>时显示</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">grunt.registerTask(&#39;des&#39;, &#39;任务描述&#39;, () &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;des task&#39;)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<pre style="background: #000; color: #ccc;">
PS C:\Users\admin\Desktop\grunt-test> yarn grunt --help 

...

Available tasks
         hello  Custom task.
           des  任务描述
</pre>


<p>异步任务,异步任务需要借助 grunt 的 async 函数</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"> grunt.registerTask(&#39;async-task&#39;, function() &#123;</span><br><span class="line">    &#x2F;&#x2F; 异步任务必须在执行之前调用this.async 并拿到返回结果</span><br><span class="line">    const done &#x3D; this.async();</span><br><span class="line">    setTimeout(function () &#123;</span><br><span class="line">        console.log(&#39;异步任务执行了&#39;)</span><br><span class="line">        done()</span><br><span class="line">    &#125;, 1000)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>默认任务，在命令行直接执行 <code>yarn grunt</code>时，会查看是否注册名为<code>default</code>的任务，有的话会执行<code>default</code>任务</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">grunt.registerTask(&#39;default&#39;, &#39;默认任务&#39;, () &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;模拟默认任务&#39;);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>串行任务，可以为注册任务指定一个任务数组，再执行该任务时会一次执行任务数组中的任务</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">grunt.registerTask(&#39;default&#39;, &#39;默认任务&#39;, [&#39;hello&#39;, &#39;des&#39;, &#39;async-task&#39;])</span><br></pre></td></tr></table></figure>

<p>任务标记失败</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 任务中返回false 代表任务失败，在串行任务中，失败的任务之后的任务不再执行</span><br><span class="line">&#x2F;&#x2F; 如果想要穿行任务失败之后的任务强制执行，可以指定 --force 的参数 </span><br><span class="line">grunt.registerTask(&#39;error-task&#39;, &#39;模拟执行失败的任务&#39;, () &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;模拟执行失败的任务&#39;);</span><br><span class="line">    return false;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>异步任务标记失败</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 异步任务标记失败</span><br><span class="line">   grunt.registerTask(&#39;async-error-task&#39;, &#39;模拟执行失败的异步任务&#39;, function() &#123;</span><br><span class="line">       const done &#x3D; this.async();</span><br><span class="line">       setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">           console.log(&#39;模拟执行失败的异步任务&#39;);</span><br><span class="line">           done(false);</span><br><span class="line">       &#125;, 1000)</span><br><span class="line">   &#125;)</span><br></pre></td></tr></table></figure>

<p>配置方法initConfig</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">grunt.initConfig(&#123;</span><br><span class="line">    name: <span class="string">&#x27;along&#x27;</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">grunt.registerTask(<span class="string">&#x27;getName&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(grunt.config(<span class="string">&#x27;name&#x27;</span>));</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h3 id="多目标任务"><a href="#多目标任务" class="headerlink" title="多目标任务"></a>多目标任务</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 多目标任务</span><br><span class="line">grunt.initConfig(&#123;</span><br><span class="line">    &#x2F;&#x2F; 任务名与注册的任务名相同</span><br><span class="line">    build: &#123;</span><br><span class="line">        &#x2F;&#x2F; options 会作为任务选项出现</span><br><span class="line">        options: &#123;</span><br><span class="line">            global: &#39;dev&#39;,</span><br><span class="line">            path: &#39;&#x2F;src&#39;</span><br><span class="line">        &#125;,</span><br><span class="line">        &#x2F;&#x2F; 除了options 其他的属性都会称为任务的一个目标任务</span><br><span class="line">        css: &#39;css任务&#39;,</span><br><span class="line">        js: &#39;js任务&#39;,</span><br><span class="line"></span><br><span class="line">        &#x2F;&#x2F; 为某个目标任务指定 options时，会替换掉全局的options中相同的属性</span><br><span class="line">        static: &#123;</span><br><span class="line">            options: &#123;</span><br><span class="line">                path: &#39;&#x2F;public&#39;,</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line">grunt.registerMultiTask(&#39;build&#39;, &#39;多目标任务&#39;, function() &#123;</span><br><span class="line">    console.log(this.options())</span><br><span class="line">    console.log(&#96;build task - target: $&#123;this.target&#125; data: $&#123;this.data&#125;&#96;)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>执行这个任务</p>
<pre style="background: #000; color: #fff;">
PS C:\Users\admin\Desktop\grunt-test> yarn grunt build
yarn run v1.22.4
$ C:\Users\admin\Desktop\grunt-test\node_modules\.bin\grunt build
Running "build:css" (build) task
{ global: 'dev', path: '/src' }
build task - target: css data: css任务

Running "build:js" (build) task
{ global: 'dev', path: '/src' }
build task - target: js data: js任务

Running "build:static" (build) task
{ global: 'dev', path: '/public' }
build task - target: static data: [object Object]
</pre>


<h3 id="插件使用"><a href="#插件使用" class="headerlink" title="插件使用"></a>插件使用</h3><p>安装清除文件插件<br><code>yarn add grunt-contrib-clean</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">grunt.initConfig(&#123;</span><br><span class="line">    &#x2F;&#x2F; 需要对应的配置</span><br><span class="line">    clean: &#123;</span><br><span class="line">        &#x2F;&#x2F; dist: &#39;dist&#x2F;index.html&#39;,</span><br><span class="line">        &#x2F;&#x2F; dist: &#39;dist&#x2F;*.txt&#39;,</span><br><span class="line">        dist: &#39;dist&#x2F;**&#39;,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 加载插件</span><br><span class="line">grunt.loadNpmTasks(&#39;grunt-contrib-clean&#39;);</span><br></pre></td></tr></table></figure>

<p>sass插件</p>
<p><code>yarn add grunt-sass sass</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">const sass &#x3D; require(&#39;sass&#39;);</span><br><span class="line"></span><br><span class="line">module.exports &#x3D; grunt &#x3D;&gt; &#123;</span><br><span class="line">    grunt.initConfig(&#123;</span><br><span class="line">        sass: &#123;</span><br><span class="line">            options: &#123;</span><br><span class="line">                implementation: sass,</span><br><span class="line">            &#125;,</span><br><span class="line">            main: &#123;</span><br><span class="line">                files: &#123;</span><br><span class="line">                    &#39;dist&#x2F;css&#x2F;main.css&#39;: &#39;src&#x2F;scss&#x2F;main.scss&#39;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line"></span><br><span class="line">    grunt.loadNpmTasks(&#39;grunt-sass&#39;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>babel</p>
<p><code>yarn add grunt-babel @babel/core @babel/preset-env</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">grunt.initConfig(&#123;</span><br><span class="line">    babel: &#123;</span><br><span class="line">        options: &#123;</span><br><span class="line">            presets: [&#39;@babel&#x2F;preset-env&#39;]</span><br><span class="line">        &#125;,</span><br><span class="line">        main: &#123;</span><br><span class="line">            files: &#123;</span><br><span class="line">                &#39;dist&#x2F;js&#x2F;app.js&#39;: &#39;src&#x2F;js&#x2F;app.js&#39;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    grunt.loadNpmTasks(&#39;grunt-babel&#39;);</span><br><span class="line">    </span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>自动加载模块</p>
<p><code>yarn add load-grunt-tasks --dev</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">const loadGruntTasks &#x3D; require(&#39;load-grunt-tasks&#39;);</span><br><span class="line"></span><br><span class="line">module.exports &#x3D; grunt &#x3D;&gt; &#123;</span><br><span class="line">    grunt.initConfig(&#123;</span><br><span class="line">        babel: &#123;</span><br><span class="line">            options: &#123;</span><br><span class="line">                sourceMap: true,</span><br><span class="line">                presets: [&#39;@babel&#x2F;preset-env&#39;]</span><br><span class="line">            &#125;,</span><br><span class="line">            main: &#123;</span><br><span class="line">                files: &#123;</span><br><span class="line">                    &#39;dist&#x2F;js&#x2F;app.js&#39;: &#39;src&#x2F;js&#x2F;app.js&#39;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;)</span><br><span class="line"></span><br><span class="line">    loadGruntTasks(grunt); &#x2F;&#x2F; 自动加载插件</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>监听文件自动编译</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add grunt-contrib-watch --dev</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line">const sass &#x3D; require(&#39;sass&#39;);</span><br><span class="line">const loadGruntTasks &#x3D; require(&#39;load-grunt-tasks&#39;);</span><br><span class="line"></span><br><span class="line">module.exports &#x3D; grunt &#x3D;&gt; &#123;</span><br><span class="line">    grunt.initConfig(&#123;</span><br><span class="line">        watch: &#123;</span><br><span class="line">            js: &#123;</span><br><span class="line">                files: [&#39;src&#x2F;js&#x2F;*.js&#39;], &#x2F;&#x2F; 坚挺的文件数组</span><br><span class="line">                tasks: [&#39;babel&#39;], &#x2F;&#x2F; 当文件变化时要执行的任务</span><br><span class="line">            &#125;,</span><br><span class="line">            css: &#123;</span><br><span class="line">                files: [&#39;src&#x2F;scss&#x2F;*.scss&#39;],</span><br><span class="line">                tasks: [&#39;sass&#39;],</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;,</span><br><span class="line"></span><br><span class="line">        babel: &#123;</span><br><span class="line">            options: &#123;</span><br><span class="line">                sourceMap: true,</span><br><span class="line">                presets: [&#39;@babel&#x2F;preset-env&#39;]</span><br><span class="line">            &#125;,</span><br><span class="line">            main: &#123;</span><br><span class="line">                files: &#123;</span><br><span class="line">                    &#39;dist&#x2F;js&#x2F;app.js&#39;: &#39;src&#x2F;js&#x2F;app.js&#39;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;,</span><br><span class="line"></span><br><span class="line">        sass: &#123;</span><br><span class="line">            options: &#123;</span><br><span class="line">                sourceMap: true,</span><br><span class="line">                implementation: sass,</span><br><span class="line">            &#125;,</span><br><span class="line">            main: &#123;</span><br><span class="line">                files: &#123;</span><br><span class="line">                    &#39;dist&#x2F;css&#x2F;main.css&#39;: &#39;src&#x2F;scss&#x2F;main.scss&#39;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line"></span><br><span class="line">    loadGruntTasks(grunt); &#x2F;&#x2F; 自动加载插件</span><br><span class="line">    </span><br><span class="line">    grunt.registerTask(&#39;default&#39;, [&#39;sass&#39;, &#39;babel&#39;, &#39;watch&#39;]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>之后被监听文件修改会自动编译</p>
<h3 id="gulp"><a href="#gulp" class="headerlink" title="gulp"></a>gulp</h3><p>安装</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add gulp --dev</span><br></pre></td></tr></table></figure>

<p>创建入口文件<code>gulpfile.js</code></p>
<p>注册任务</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">exports.foo &#x3D;  done &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;foo&#39;)</span><br><span class="line">    done();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>执行<code>yarn gulp foo</code></p>
<p>注册默认任务</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">exports.default &#x3D;  done &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;defalt&#39;)</span><br><span class="line">    done();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>组合任务<br>组合任务可以注册串行任务和并行任务</p>
<ul>
<li>串行任务</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">const &#123;series, parallel&#125; &#x3D; require(&#39;gulp&#39;);</span><br><span class="line"></span><br><span class="line">const task1 &#x3D; done &#x3D;&gt; &#123;</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">        console.log(&#39;task1 running~&#39;);</span><br><span class="line">        done();</span><br><span class="line">    &#125;, 2000)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">const task2 &#x3D; done &#x3D;&gt; &#123;</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">        console.log(&#39;task2 running~&#39;);</span><br><span class="line">        done();</span><br><span class="line">    &#125;, 2000)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">const task3 &#x3D; done &#x3D;&gt; &#123;</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">        console.log(&#39;task3 running~&#39;);</span><br><span class="line">        done();</span><br><span class="line">    &#125;, 2000)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; gulp 组合任务</span><br><span class="line">exports.default &#x3D; series(task1, task2, task3);</span><br></pre></td></tr></table></figure>

<pre style="background: #000;color: #ccc">
PS C:\Users\admin\Desktop\gulp-demo> yarn gulp
$ C:\Users\admin\Desktop\gulp-demo\node_modules\.bin\gulp
[00:53:37] Using gulpfile ~\Desktop\gulp-demo\gulpfile.js
[00:53:37] Starting 'default'...
[00:53:37] Starting 'task1'...
task1 running~
[00:53:39] Finished 'task1' after 2.03 s
[00:53:39] Starting 'task2'...
task2 running~
[00:53:41] Finished 'task2' after 2.01 s
[00:53:41] Starting 'task3'...
task3 running~
[00:53:43] Finished 'task3' after 2.01 s
[00:53:43] Finished 'default' after 6.08 s
Done in 7.36s.
</pre>

<ul>
<li>并行任务</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 注册上面代码三个任务的并行任务</span><br><span class="line">exports.default &#x3D; parallel(task1, task2, task3);</span><br></pre></td></tr></table></figure>

<pre style="background: #000; color: #ccc">
PS C:\Users\admin\Desktop\gulp-demo> yarn gulp
yarn run v1.22.4
$ C:\Users\admin\Desktop\gulp-demo\node_modules\.bin\gulp
[00:57:27] Using gulpfile ~\Desktop\gulp-demo\gulpfile.js
[00:57:27] Starting 'default'...
[00:57:27] Starting 'task1'...
[00:57:27] Starting 'task2'...
[00:57:27] Starting 'task3'...
task1 running~
[00:57:29] Finished 'task1' after 2.01 s
task2 running~
[00:57:29] Finished 'task2' after 2.04 s
task3 running~
[00:57:29] Finished 'task3' after 2.05 s
[00:57:29] Finished 'default' after 2.1 s
Done in 3.64s.
</pre>

<p>gulp异步任务</p>
<ul>
<li>promise异步任务</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; gulp 异步任务</span><br><span class="line">&#x2F;&#x2F; promise 返回成功时会忽略 promise 的返回值</span><br><span class="line">exports.promise &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;promise task~&#39;);</span><br><span class="line">    return Promise.resolve();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">exports.promise_error &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;promise error task~&#39;);</span><br><span class="line">    return Promise.reject(new Error(&#39;task failed~&#39;));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>async 异步任务</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; async 异步任务</span><br><span class="line">const timeout &#x3D; time &#x3D;&gt; &#123;</span><br><span class="line">    return new Promise(resolve &#x3D;&gt; &#123;</span><br><span class="line">        setTimeout(resolve, time);</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">exports.async &#x3D; async () &#x3D;&gt; &#123;</span><br><span class="line">    await timeout(1000);</span><br><span class="line">    console.log(&#39;async task &#39;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>stream 文件流</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">exports.stream &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    const readStream &#x3D; fs.createReadStream(&#39;package.json&#39;);</span><br><span class="line">    const writeStream &#x3D; fs.createWriteStream(&#39;temp.txt&#39;);</span><br><span class="line">    readStream.pipe(writeStream);</span><br><span class="line">    return readStream;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="gulp-构建过程核心原理"><a href="#gulp-构建过程核心原理" class="headerlink" title="gulp 构建过程核心原理"></a>gulp 构建过程核心原理</h4><p>gulp是基于流的构建</p>
<p>读取流 =&gt; 转换流 =&gt; 写入流</p>
<p>创建文件<code>css/style.css</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;* 样式文件 *&#x2F;</span><br><span class="line"></span><br><span class="line">body &#123;</span><br><span class="line">    color: #333;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#x2F;* 样式结束 *&#x2F;</span><br></pre></td></tr></table></figure>

<p>先手动创建一个输出文件夹<code>dist/css/style.css</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">const fs &#x3D; require(&#39;fs&#39;);</span><br><span class="line">&#x2F;&#x2F; 借助stream的转换流读取做css的转换</span><br><span class="line">const &#123;Transform&#125; &#x3D; require(&#39;stream&#39;);</span><br><span class="line">exports.css &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    &#x2F;&#x2F; 读取文件</span><br><span class="line">    const read &#x3D; fs.createReadStream(&#39;css&#x2F;style.css&#39;);</span><br><span class="line">    &#x2F;&#x2F; 文件写入流</span><br><span class="line">    const write &#x3D; fs.createWriteStream(&#39;dist&#x2F;css&#x2F;style.min.css&#39;);</span><br><span class="line">    &#x2F;&#x2F; 文件转换流</span><br><span class="line">    const transform &#x3D; new Transform(&#123;</span><br><span class="line">        transform: (chunk, encoding, callback) &#x3D;&gt; &#123;</span><br><span class="line">            &#x2F;&#x2F; check &#x3D;&gt; 读取流的文件内容（Buffer）</span><br><span class="line">            const input &#x3D; chunk.toString();</span><br><span class="line">            &#x2F;&#x2F; 替换掉 空格和注释</span><br><span class="line">            const output &#x3D; input.replace(&#x2F;\s+&#x2F;g, &#39;&#39;).replace(&#x2F;\&#x2F;\*.+?\*\&#x2F;&#x2F;g, &#39;&#39;);</span><br><span class="line">            </span><br><span class="line">            callback(null, output);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line"></span><br><span class="line">    read</span><br><span class="line">        .pipe(transform)</span><br><span class="line">        .pipe(write);</span><br><span class="line"></span><br><span class="line">    return read;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>接下执行<code>yarn gulp css</code>,可以看到<code>dist/css</code>下输出的文件<code>style.min.css</code>, 其中内容是处理压缩之后的<br>body{color:#333;}</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="gulp-提供了自己的文件API"><a href="#gulp-提供了自己的文件API" class="headerlink" title="gulp 提供了自己的文件API"></a>gulp 提供了自己的文件API</h4><p>通过gulp自己的api实现文件写入读取流</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">const &#123;src, dest&#125; &#x3D; require(&#39;gulp&#39;)</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">exports.fs &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return src(&#39;css&#x2F;style.css&#39;) &#x2F;&#x2F; &#39;*.css&#39;</span><br><span class="line">        .pipe(dest(&#39;dist&#39;));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="fs-与-css-压缩"><a href="#fs-与-css-压缩" class="headerlink" title="fs 与 css 压缩"></a>fs 与 css 压缩</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add gulp-clean-css --dev</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 引入css压缩插件</span><br><span class="line">const cleanCss &#x3D; require(&#39;gulp-clean-css&#39;);</span><br><span class="line"></span><br><span class="line">exports.fscss &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return src(&#39;css&#x2F;*.css&#39;)</span><br><span class="line">        .pipe(cleanCss())</span><br><span class="line">        .pipe(dest(&#39;dest&#39;));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>可以看到输出的css压缩文件在dest目录下</p>
<h4 id="重命名插件"><a href="#重命名插件" class="headerlink" title="重命名插件"></a>重命名插件</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add gulp-rename --dev</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 修改拓展名</span><br><span class="line">const cleanCss &#x3D; require(&#39;gulp-clean-css&#39;);</span><br><span class="line"></span><br><span class="line">const rename &#x3D; require(&#39;gulp-rename&#39;);</span><br><span class="line"></span><br><span class="line">exports.fscss &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return src(&#39;css&#x2F;*.css&#39;)</span><br><span class="line">        .pipe(cleanCss())</span><br><span class="line">        .pipe(rename(&#123; extname: &#39;.min.css&#39; &#125;))</span><br><span class="line">        .pipe(dest(&#39;dest&#39;));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="sass-文件编译"><a href="#sass-文件编译" class="headerlink" title="sass 文件编译"></a>sass 文件编译</h4><p>安装 <code>grunt-sass</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">const &#123;src, dest&#125; &#x3D; require(&#39;gulp&#39;);</span><br><span class="line">const sass &#x3D; require(&#39;gulp-sass&#39;);</span><br><span class="line"></span><br><span class="line">const style &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return src(&#39;src&#x2F;assets&#x2F;styles&#x2F;*.scss&#39;, &#123;base: &#39;src&#39;&#125;) &#x2F;&#x2F; base src 保留转换前的基础路径</span><br><span class="line">        .pipe(sass(&#123;</span><br><span class="line">            outputStyle: &#39;expanded&#39;, &#x2F;&#x2F; 代表编译后大括号完全展开</span><br><span class="line">        &#125;)) &#x2F;&#x2F; 下户线开头的css 文件默认不会被转换</span><br><span class="line">        .pipe(dest(&#39;dist&#39;));</span><br><span class="line">&#125;</span><br><span class="line">module.exports &#x3D; &#123;</span><br><span class="line">    style</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="脚本文件编译"><a href="#脚本文件编译" class="headerlink" title="脚本文件编译"></a>脚本文件编译</h4><p>安装<code>gulp-babel @babel/core @babel/preset-env</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">const &#123;src, dest&#125; &#x3D; require(&#39;gulp&#39;);</span><br><span class="line"></span><br><span class="line">const babel &#x3D; require(&#39;gulp-babel&#39;);</span><br><span class="line">const script &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return src(&#39;src&#x2F;assets&#x2F;scripts&#x2F;*.js&#39;, &#123;</span><br><span class="line">        base: &#39;src&#39;</span><br><span class="line">    &#125;)</span><br><span class="line">        .pipe(babel(&#123;</span><br><span class="line">            presets: [&#39;@babel&#x2F;preset-env&#39;]</span><br><span class="line">        &#125;))</span><br><span class="line">        .pipe(dest(&#39;dist&#39;));</span><br><span class="line">&#125;</span><br><span class="line">module.exports &#x3D; &#123;</span><br><span class="line">    script,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="模板文件编译"><a href="#模板文件编译" class="headerlink" title="模板文件编译"></a>模板文件编译</h4><p>可以借助<code>gulp-swig</code></p>
<p>swig 语法这里不过多描述</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">const page &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return src(&#39;src&#x2F;**&#x2F;*.html&#39;, &#123;base: &#39;src&#39;&#125;) &#x2F;&#x2F; src 下任意子目录下的任意html文件</span><br><span class="line">        .pipe(swig(&#123;data: &#123;title: &#39;along&#39;&#125;&#125;))</span><br><span class="line">        .pipe(dest(&#39;dist&#39;))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="图片字体文件"><a href="#图片字体文件" class="headerlink" title="图片字体文件"></a>图片字体文件</h4><p>安装<code>gulp-imagemin</code>,图片可以无损压缩</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">const iamgemin &#x3D; require(&#39;gulp-imagemin&#39;);</span><br><span class="line">const image &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return src(&#39;src&#x2F;assets&#x2F;images&#x2F;**&#39;, &#123;base: &#39;sec&#39;&#125;)</span><br><span class="line">        .pipe(imagemin())</span><br><span class="line">        .pipe(dest(&#39;dist&#39;))</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 字体文件不需要特殊处理，只是里边的svg同样可以借助imagemin 来压缩</span><br><span class="line">const font &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return src(&#39;src&#x2F;assets&#x2F;fonts&#x2F;**&#39;, &#123;base: &#39;sec&#39;&#125;)</span><br><span class="line">        .pipe(imagemin())</span><br><span class="line">        .pipe(dest(&#39;dist&#39;))</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="清除文件"><a href="#清除文件" class="headerlink" title="清除文件"></a>清除文件</h4><p>安装<code>del</code> del 模块不是gulp模块不过可以在gulp中使用</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add del --dev</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">const del &#x3D; require(&#39;del&#39;);</span><br><span class="line">&#x2F;&#x2F; 清除文件</span><br><span class="line">const clean &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return del([&#39;dist&#39;]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="自动加载插件"><a href="#自动加载插件" class="headerlink" title="自动加载插件"></a>自动加载插件</h4><p>安装<code> gulp-load-plugins</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">const loadPlugins &#x3D; require(&#39;gulp-load-plugins&#39;);</span><br><span class="line">const plugins &#x3D; loadPlugins();</span><br><span class="line">&#x2F;&#x2F; 之后可以通过plguns[plugin name] 来使用自动加载的插件</span><br><span class="line">const image &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return src(&#39;src&#x2F;assets&#x2F;images&#x2F;**&#39;, &#123;base: &#39;src&#39;&#125;)</span><br><span class="line">        .pipe(plugins.imagemin())</span><br><span class="line">        .pipe(dest(&#39;dist&#39;))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>如果插件名称gulp后有多个横线，会自动你转为驼峰的方式</p>
<h4 id="gulp-开发服务器"><a href="#gulp-开发服务器" class="headerlink" title="gulp 开发服务器"></a>gulp 开发服务器</h4><p>安装 <code>browser-sync</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">const &#123;src, dest, series, parallel, watch&#125; &#x3D; require(&#39;gulp&#39;);</span><br><span class="line"></span><br><span class="line">const browserSync &#x3D; require(&#39;browser-sync&#39;);</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 创建一个开发服务器</span><br><span class="line">const bs &#x3D; browserSync.create();</span><br><span class="line"></span><br><span class="line">const serve &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    &#x2F;&#x2F; 监听源代码自动编译</span><br><span class="line">    watch(&#39;src&#x2F;assets&#x2F;styles&#x2F;*.scss&#39;, style);</span><br><span class="line">    watch(&#39;src&#x2F;assets&#x2F;scripts&#x2F;*.js&#39;, script);</span><br><span class="line">    watch(&#39;src&#x2F;*.html&#39;, page);</span><br><span class="line">    watch([</span><br><span class="line">        &#39;src&#x2F;assets&#x2F;images&#x2F;**&#39;,</span><br><span class="line">        &#39;src&#x2F;assets&#x2F;fonts&#x2F;**&#39;,</span><br><span class="line">        &#39;public&#x2F;**&#39;</span><br><span class="line">    ], bs.reload);</span><br><span class="line">    </span><br><span class="line"></span><br><span class="line">    bs.init(&#123;</span><br><span class="line">        notify: false, &#x2F;&#x2F; 打开浏览器后，右上角不再显示连接成功的提示</span><br><span class="line">        port: 2080,</span><br><span class="line">        open: true,</span><br><span class="line">        files: &#39;dist&#x2F;**&#39;, &#x2F;&#x2F; 监听dist下的文件变化</span><br><span class="line">        server: &#123;</span><br><span class="line">            &#x2F;&#x2F; baseDir: &#39;dist&#39;,</span><br><span class="line">            baseDir: [&#39;dist&#39;, &#39;src&#39;, &#39;public&#39;], &#x2F;&#x2F; 指定为数组 时开发环境会一次从数组中的目录寻找文件，这种方式可以避免在开发环境打包静态资源，从而提升开发构建速度</span><br><span class="line">            routes: &#123;</span><br><span class="line">                &#39;&#x2F;node_modules&#39;: &#39;node_modules&#39; </span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>bs.init 也可以不通过files字段监听dist目录，可以通过流的方式进行编译文件向浏览器的推送 通过<code>.pipe(bs.reload(&#123;stream: true&#125;)) </code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">const page &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return src(&#39;src&#x2F;**&#x2F;*.html&#39;, &#123;base: &#39;src&#39;&#125;) &#x2F;&#x2F; src 下任意子目录下的任意html文件</span><br><span class="line">        .pipe(swig(&#123;data: pagedata&#125;))</span><br><span class="line">        .pipe(dest(&#39;dist&#39;))</span><br><span class="line">        .pipe(bs.reload(&#123;stream: true&#125;)) </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">const style &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return src(&#39;src&#x2F;assets&#x2F;styles&#x2F;*.scss&#39;, &#123;base: &#39;src&#39;&#125;) &#x2F;&#x2F; base src 保留转换前的基础路径</span><br><span class="line">        .pipe(sass(&#123;</span><br><span class="line">            outputStyle: &#39;expanded&#39;, &#x2F;&#x2F; 代表编译后大括号完全展开</span><br><span class="line">        &#125;)) &#x2F;&#x2F; 下户线开头的css 文件默认不会被转换</span><br><span class="line">        .pipe(dest(&#39;dist&#39;))</span><br><span class="line">        .pipe(bs.reload(&#123;stream: true&#125;)) &#x2F;&#x2F; 以流的方式像浏览器推送变化</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">const script &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return src(&#39;src&#x2F;assets&#x2F;scripts&#x2F;*.js&#39;, &#123;</span><br><span class="line">        base: &#39;src&#39;</span><br><span class="line">    &#125;)</span><br><span class="line">        .pipe(babel(&#123;</span><br><span class="line">            presets: [&#39;@babel&#x2F;preset-env&#39;]</span><br><span class="line">        &#125;))</span><br><span class="line">        .pipe(dest(&#39;dist&#39;))</span><br><span class="line">        .pipe(bs.reload(&#123;stream: true&#125;)) </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="文件压缩"><a href="#文件压缩" class="headerlink" title="文件压缩"></a>文件压缩</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add gulp-htmlmin gulp-uglify gulp-clean-css --dev</span><br></pre></td></tr></table></figure>

<p>额外安装一个判断文件类型的操作</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add gulp-if --dev</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">const useref &#x3D; () &#x3D;&gt; &#123;</span><br><span class="line">    return src(&#39;temp&#x2F;**&#x2F;*.html&#39;, &#123;base: &#39;temp&#39;&#125;)</span><br><span class="line">        .pipe(plugins.useref(&#123;searchPath: [&#39;temp&#39;, &#39;.&#39;]&#125;))</span><br><span class="line">        .pipe(plugins.if(&#x2F;\.js$&#x2F;, plugins.uglify()))</span><br><span class="line">        .pipe(plugins.if(&#x2F;\.css$&#x2F;, plugins.cleanCss()))</span><br><span class="line">        .pipe(plugins.if(&#x2F;\.html$&#x2F;, plugins.htmlmin(&#123;</span><br><span class="line">            collapseWhitespace: true, &#x2F;&#x2F; 压缩html</span><br><span class="line">            minifyCSS: true, &#x2F;&#x2F; 压缩行内css</span><br><span class="line">            minifyJS: true, &#x2F;&#x2F; 压缩行内js</span><br><span class="line">        &#125;)))</span><br><span class="line">        .pipe(dest(&#39;dist&#39;))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</section>
    <!-- Tags START -->
    
      <div class="tags">
        <span>Tags:</span>
        
  <a href="/tags#自动化" >
    <span class="tag-code">自动化</span>
  </a>

      </div>
    
    <!-- Tags END -->
    <!-- NAV START -->
    
  <div class="nav-container">
    <!-- reverse left and right to put prev and next in a more logic postition -->
    
      <a class="nav-left" href="/2020/08/27/%E8%84%9A%E6%89%8B%E6%9E%B6%E5%B7%A5%E5%85%B7/">
        <span class="nav-arrow">← </span>
        
          脚手架工具
        
      </a>
    
    
      <a class="nav-right" href="/2020/08/27/webpack/">
        
          webpack
        
        <span class="nav-arrow"> →</span>
      </a>
    
  </div>

    <!-- NAV END -->
    <!-- 打赏 START -->
    
      <div class="money-like">
        <div class="reward-btn">
          赏
          <span class="money-code">
            <span class="alipay-code">
              <div class="code-image"></div>
              <b>使用支付宝打赏</b>
            </span>
            <span class="wechat-code">
              <div class="code-image"></div>
              <b>使用微信打赏</b>
            </span>
          </span>
        </div>
        <p class="notice">若你觉得我的文章对你有帮助，欢迎点击上方按钮对我打赏</p>
      </div>
    
    <!-- 打赏 END -->
    <!-- 二维码 START -->
    
      <div class="qrcode">
        <canvas id="share-qrcode"></canvas>
        <p class="notice">扫描二维码，分享此文章</p>
      </div>
    
    <!-- 二维码 END -->
    
      <!-- No Comment -->
    
  </article>
  <!-- Article END -->
  <!-- Catalog START -->
  
    <aside class="catalog-container">
  <div class="toc-main">
    <strong class="toc-title">Catalog</strong>
    
      <ol class="toc-nav"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#%E5%89%8D%E7%AB%AF%E8%87%AA%E5%8A%A8%E5%8C%96"><span class="toc-nav-text">前端自动化</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#grunt"><span class="toc-nav-text">grunt</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#%E5%A4%9A%E7%9B%AE%E6%A0%87%E4%BB%BB%E5%8A%A1"><span class="toc-nav-text">多目标任务</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8"><span class="toc-nav-text">插件使用</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#gulp"><span class="toc-nav-text">gulp</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#gulp-%E6%9E%84%E5%BB%BA%E8%BF%87%E7%A8%8B%E6%A0%B8%E5%BF%83%E5%8E%9F%E7%90%86"><span class="toc-nav-text">gulp 构建过程核心原理</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#gulp-%E6%8F%90%E4%BE%9B%E4%BA%86%E8%87%AA%E5%B7%B1%E7%9A%84%E6%96%87%E4%BB%B6API"><span class="toc-nav-text">gulp 提供了自己的文件API</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#fs-%E4%B8%8E-css-%E5%8E%8B%E7%BC%A9"><span class="toc-nav-text">fs 与 css 压缩</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#%E9%87%8D%E5%91%BD%E5%90%8D%E6%8F%92%E4%BB%B6"><span class="toc-nav-text">重命名插件</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#sass-%E6%96%87%E4%BB%B6%E7%BC%96%E8%AF%91"><span class="toc-nav-text">sass 文件编译</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#%E8%84%9A%E6%9C%AC%E6%96%87%E4%BB%B6%E7%BC%96%E8%AF%91"><span class="toc-nav-text">脚本文件编译</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#%E6%A8%A1%E6%9D%BF%E6%96%87%E4%BB%B6%E7%BC%96%E8%AF%91"><span class="toc-nav-text">模板文件编译</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#%E5%9B%BE%E7%89%87%E5%AD%97%E4%BD%93%E6%96%87%E4%BB%B6"><span class="toc-nav-text">图片字体文件</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#%E6%B8%85%E9%99%A4%E6%96%87%E4%BB%B6"><span class="toc-nav-text">清除文件</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#%E8%87%AA%E5%8A%A8%E5%8A%A0%E8%BD%BD%E6%8F%92%E4%BB%B6"><span class="toc-nav-text">自动加载插件</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#gulp-%E5%BC%80%E5%8F%91%E6%9C%8D%E5%8A%A1%E5%99%A8"><span class="toc-nav-text">gulp 开发服务器</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#%E6%96%87%E4%BB%B6%E5%8E%8B%E7%BC%A9"><span class="toc-nav-text">文件压缩</span></a></li></ol></li></ol></li></ol>
    
  </div>
</aside>
  
  <!-- Catalog END -->
</main>

<script>
  (function () {
    var url = 'https://github.com/alongithub/2020/08/27/自动化构建/';
    var banner = ''
    if (banner !== '' && banner !== 'undefined' && banner !== 'null') {
      $('#article-banner').css({
        'background-image': 'url(' + banner + ')'
      })
    } else {
      $('#article-banner').geopattern(url)
    }
    $('.header').removeClass('fixed-header')

    // error image
    $(".markdown-content img").on('error', function() {
      $(this).attr('src', '/css/images/error_icon.png')
      $(this).css({
        'cursor': 'default'
      })
    })

    // zoom image
    $(".markdown-content img").on('click', function() {
      var src = $(this).attr('src')
      if (src !== '/css/images/error_icon.png') {
        var imageW = $(this).width()
        var imageH = $(this).height()

        var zoom = ($(window).width() * 0.95 / imageW).toFixed(2)
        zoom = zoom < 1 ? 1 : zoom
        zoom = zoom > 2 ? 2 : zoom
        var transY = (($(window).height() - imageH) / 2).toFixed(2)

        $('body').append('<div class="image-view-wrap"><div class="image-view-inner"><img src="'+ src +'" /></div></div>')
        $('.image-view-wrap').addClass('wrap-active')
        $('.image-view-wrap img').css({
          'width': `${imageW}`,
          'transform': `translate3d(0, ${transY}px, 0) scale3d(${zoom}, ${zoom}, 1)`
        })
        $('html').css('overflow', 'hidden')

        $('.image-view-wrap').on('click', function() {
          $(this).remove()
          $('html').attr('style', '')
        })
      }
    })
  })();
</script>


  <script>
    var qr = new QRious({
      element: document.getElementById('share-qrcode'),
      value: document.location.href
    });
  </script>






    <div class="scroll-top">
  <span class="arrow-icon"></span>
</div>
    <footer class="app-footer">
  <p class="copyright">
    Copyright&copy; 2019-2022 along
    <br>
    <a href="https://beian.miit.gov.cn/" target="_blank">京ICP备2020044791号-1</a>
    <!-- <br>
    Theme by <a href="https://github.com/alongithub">alongithub</a>
     -->
  </p>
</footer>

<script>
  function async(u, c) {
    var d = document, t = 'script',
      o = d.createElement(t),
      s = d.getElementsByTagName(t)[0];
    o.src = u;
    if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
    s.parentNode.insertBefore(o, s);
  }
</script>
<script>
  async("/cdn.along/fastclick/1.0.6/fastclick.min.js", function(){
    FastClick.attach(document.body);
  })
</script>

<script>
  var hasLine = 'true';
  async("/cdn.along/highlight.js/9.12.0/highlight.min.js", function(){
    $('figure pre').each(function(i, block) {
      var figure = $(this).parents('figure');
      if (hasLine === 'false') {
        figure.find('.gutter').hide();
      }
      hljs.configure({useBR: true});
      var lang = figure.attr('class').split(' ')[1] || 'code';
      var codeHtml = $(this).html();
      var codeTag = document.createElement('code');
      codeTag.className = lang;
      codeTag.innerHTML = codeHtml;
      $(this).attr('class', '').empty().html(codeTag);
      figure.attr('data-lang', lang.toUpperCase());
      hljs.highlightBlock(block);
    });
  })
</script>
<!-- Baidu Tongji -->


<script src="/js/script.js"></script>


  </body>
</html>